<template>
  <div
    class="virtual-scroll-container"
    :style="{ height: containerHeight + 'px' }"
    @scroll="handleScroll"
    ref="containerRef"
  >
    <div class="virtual-scroll-content" :style="{ height: totalHeight + 'px' }">
      <div
        class="virtual-scroll-items"
        :style="{ transform: `translateY(${offsetY}px)` }"
      >
        <div
          v-for="item in visibleItems"
          :key="item.id"
          class="virtual-scroll-item"
          :style="{ height: itemHeight + 'px' }"
        >
          {{ item.text }}
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from "vue";

interface VirtualScrollItem {
  id: number;
  text: string;
}

interface Props {
  items: VirtualScrollItem[];
  itemHeight: number;
  containerHeight: number;
}

const props = withDefaults(defineProps<Props>(), {
  itemHeight: 50,
  containerHeight: 400,
});

const containerRef = ref<HTMLElement>();
const scrollTop = ref(0);

// 计算总高度
const totalHeight = computed(() => props.items.length * props.itemHeight);

// 计算可见区域
const visibleStart = computed(() =>
  Math.floor(scrollTop.value / props.itemHeight)
);

const visibleEnd = computed(() =>
  Math.min(
    visibleStart.value +
      Math.ceil(props.containerHeight / props.itemHeight) +
      1,
    props.items.length
  )
);

// 计算可见项目
const visibleItems = computed(() =>
  props.items.slice(visibleStart.value, visibleEnd.value)
);

// 计算偏移量
const offsetY = computed(() => visibleStart.value * props.itemHeight);

// 处理滚动事件
const handleScroll = (event: Event) => {
  const target = event.target as HTMLElement;
  scrollTop.value = target.scrollTop;
};

// 滚动到指定位置
const scrollTo = (index: number) => {
  if (containerRef.value) {
    const scrollTop = index * props.itemHeight;
    containerRef.value.scrollTop = scrollTop;
  }
};

// 暴露方法给父组件
defineExpose({
  scrollTo,
});
</script>

<style scoped>
.virtual-scroll-container {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  overflow: auto;
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.virtual-scroll-content {
  position: relative;
}

.virtual-scroll-items {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.virtual-scroll-item {
  display: flex;
  align-items: center;
  padding: 0 16px;
  border-bottom: 1px solid #f0f0f0;
  font-size: 14px;
  color: #333;
  transition: background-color 0.2s;
}

.virtual-scroll-item:hover {
  background-color: #f5f5f5;
}

.virtual-scroll-item:nth-child(even) {
  background-color: #fafafa;
}

.virtual-scroll-item:nth-child(even):hover {
  background-color: #f0f0f0;
}
</style>
